package com.mcxx.modules.formulcount;

import com.alibaba.fastjson.JSONObject;
import com.mcxx.formulcount.gonshi.BlockServer;
import com.mcxx.formulcount.gonshi.FormulaConvert;
import com.mcxx.formulcount.gonshi.ISentence;
import com.mcxx.formulcount.gonshi.RefObject;
import com.mcxx.formulcount.param.FormulCountParam;
import com.mcxx.formulcount.param.SecurityParam;
import com.mcxx.modules.base.service.read.DictionaryReadService;
import com.mcxx.modules.miniSalvation.order.entity.StandardEntity;
import com.mcxx.modules.miniSalvation.order.service.read.StandardHistoryReadService;
import com.mcxx.modules.system.entity.SalvationRuleEntity;
import com.mcxx.modules.system.service.read.SalvationRuleReadService;
import com.mcxx.result.BaseResult;
import com.mcxx.util.CommonUtil;
import com.mcxx.util.Constant;
import com.mcxx.util.FailureCode;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;


@Service
public class FormulCountStandHisService extends FormulCountService {
    private final static Logger logger = LoggerFactory.getLogger(FormulCountStandHisService.class);
    @Autowired
    private SalvationRuleReadService salvationRuleReadService;
    @Autowired
    private StandardHistoryReadService standardReadService;


    @Override
    public BaseResult<List<SecurityParam>> exceptionalFormulCount(FormulCountParam param) {
        BaseResult<List<SecurityParam>> result = new BaseResult<>();
        List<SecurityParam> securityList = new ArrayList<>();
        if (CommonUtil.invalidArgs(param.getAreaCode(), param.getBusinessType(), param.getTaOrgId(), param.getTypeName())) {
            result.setCode(FailureCode.ERR_10000.getCode());
            result.setMsg(FailureCode.ERR_10000.getMessage());
            return result;
        }
        param.setAreaCode(param.getAreaCode());
        param.setBusinessType(param.getBusinessType());
        param.setTaOrgId(param.getTaOrgId());
        if (null == param.getDisabilityLevel() || "".equals(param.getDisabilityLevel())) {
            param.setDisabilityLevel("无");
        }
        try {
            if (param.getTypeName().indexOf("城市") != -1) {
                param.setType("03");
            } else {
                param.setType("04");
            }

            logger.info("获取救助标准：{}", param);
            Double standardMoneys = standardReadService.getStandardMoney(param.getWelfareId(), param.getAreaCode().substring(0,6)+"000000", param.getBusinessType(), param.getType());
            logger.info("救助标准结果：{}", standardMoneys);
            if (null != standardMoneys) {
                Double standardMoney = standardMoneys;
                List<SalvationRuleEntity> list = salvationRuleReadService.queryRuleCount(param);
                if (null != list && list.size() > 0) {
                    for (SalvationRuleEntity entity : list) {
                        SecurityParam securityParam = new SecurityParam();

                        securityParam.setStandardMoney(standardMoney);
                        Map<String, Object> varValues = exceptionalValue(param);
                        varValues.put("健康状况", param.getHealth() == null ? "无" : param.getHealth());
                        varValues.put("重病病种", param.getSeverediseases() == null ? "无" : param.getSeverediseases());
                        varValues.put("残疾等级", param.getDisabilityLevel());
                        varValues.put("年龄", Integer.parseInt(param.getAge() == null ? "0" : param.getAge()));
                        varValues.put("文化程度", param.getEducation() == null ? "无" : param.getEducation());
                        varValues.put("是否在校", param.getIsAtSchool() == null ? "无" : param.getIsAtSchool());
                        if (null != varValues && varValues.size() > 0) {
                            for (String str : varValues.keySet()) {
                                if (str.indexOf("理") != -1) {
                                    String typeName = param.getTypeName().substring(0, 2) + varValues.get(str).toString() + "标准";
                                    Map<String, Object> standParam = new HashMap<>();
                                    standParam.put("status", Constant.StandardStatus.ENABLE);
                                    standParam.put("typeName", typeName);
                                    standParam.put("welfareId", param.getWelfareId());
                                    standParam.put("orgId", param.getTaOrgId());
                                    standParam.put("areaCode", param.getAreaCode().substring(0,6)+"000000");
                                    StandardEntity saentity = standardReadService.querySalvationStandard(standParam);
                                    if (null != saentity) {
                                        securityParam.setTypeName(saentity.getType());
                                        securityParam.setTypeMoney(saentity.getStandardMoney());
                                        varValues.put(saentity.getType(), saentity.getStandardMoney());
                                    } else {
                                        logger.error("标准为零，请先配置标准, param={}", param);
                                        result.setCode("300");
                                        result.setMsg("标准为零，请先配置标准");
                                        return result;
                                    }
                                }
                            }
                        }
                        if (param.getTypeName().indexOf("城市") != -1) {
                            varValues.put("城市特困基本生活标准", standardMoney);
                        } else {
                            varValues.put("农村特困基本生活标准", standardMoney);
                        }
                        String str = entity.getChineseFormula();
                        if (str.indexOf("生活自理能力") != -1) {
                            if (StringUtils.isNotBlank(param.getOneself())) {

                                FormulaConvert cvt = new FormulaConvert();
                                ArrayList<String> arr = cvt.SplitWord("{" + str + "}");
                                RefObject rnt = new RefObject(0);
                                ArrayList<ISentence> sts = BlockServer.build(arr, 0, rnt);

                                Map<String, Object> rnts = BlockServer.runCode(sts, varValues);
                                if (null != rnts && rnts.size() > 0) {
                                    for (String k : rnts.keySet()) {
                                        securityParam.setMoneyName(k);
                                        securityParam.setMoney(rnts.get(k).toString());
                                    }
                                    securityList.add(securityParam);
                                }
                            }
                        } else {

                            FormulaConvert cvt = new FormulaConvert();
                            ArrayList<String> arr = cvt.SplitWord("{" + str + "}");
                            RefObject rnt = new RefObject(0);
                            ArrayList<ISentence> sts = BlockServer.build(arr, 0, rnt);

                            Map<String, Object> rnts = BlockServer.runCode(sts, varValues);
                            if (null != rnts && rnts.size() > 0) {
                                for (String k : rnts.keySet()) {
                                    securityParam.setMoneyName(k);
                                    securityParam.setMoney(rnts.get(k).toString());
                                }
                                securityList.add(securityParam);
                            }
                        }
                    }
                    if(securityList.size() == 0) {
                        result.setCode("400");
                        result.setMsg("根据政策公式无法计算结果，请检查政策配置是否正确");
                        logger.error("根据政策公式无法计算结果, varValues={}", param);
                        logger.error("政策配置：{}", JSONObject.toJSONString(list));
                        return result;
                    }
                } else {
                    result.setCode("400");
                    result.setMsg("规则为空，请先配置规则");
                    logger.error("规则为空，请先配置规则, param={}", param);
                    return result;
                }
            } else {
                logger.error("标准为零，请先配置标准, param={}", param);
                result.setCode("300");
                result.setMsg("标准为零，请先配置标准");
            }
            moneyRound(securityList);
            result.setData(securityList);
        } catch (Exception e1) {
            logger.error("param={}, {}", param, e1);
            result.setCode(FailureCode.ERR_20017.getCode());
            result.setMsg(e1.getMessage());
        }
        return result;
    }


    @Override
    public BaseResult<List<SecurityParam>> drbFormulCount(FormulCountParam param) {
        BaseResult<List<SecurityParam>> result = new BaseResult<>();
        List<SecurityParam> securityList = new ArrayList<>();
        if (CommonUtil.invalidArgs(param.getAreaCode(), param.getBusinessType(), param.getTaOrgId(),
                param.getTypeName())) {
            result.setCode(FailureCode.ERR_10000.getCode());
            result.setMsg(FailureCode.ERR_10000.getMessage());
            return result;
        }
        param.setAreaCode(param.getAreaCode());
        param.setBusinessType(param.getBusinessType());
        param.setTaOrgId(param.getTaOrgId());
        param.setSaveType(Constant.SaveType.DRB);
        try {
            if (param.getTypeName().indexOf("城市") != -1) {
                param.setType("01");
            } else {
                param.setType("02");
            }

            Double standardMoneys = standardReadService.getStandardMoney(param.getWelfareId(), param.getAreaCode().substring(0,6)+"000000", param.getBusinessType(), param.getType());
            Double standardMoney;
            if (null == standardMoneys) {
                result.setCode("300");
                result.setMsg("标准为零，请先配置标准");
                return result;
            }
            else{
                standardMoney = standardMoneys;
            }

            if(null==param.getIncome()){
                result.setCode("300");
                result.setMsg("家庭收入为空");
                return result;
            }

            if ( param.getIncome() <= standardMoney || param.getIncome()> standardMoney*1.5) {
                result.setCode("300");
                result.setMsg("家庭收入没有在救助标准"+standardMoney+"的1-1.5倍之间");
                return result;
            }

            if(Constant.GuaranteeType.POLICY.equals(param.getFormulaValue())){

                List<SalvationRuleEntity> list = salvationRuleReadService.queryRuleCount(param);
                if (null == list || list.size() == 0) {
                    result.setCode("400");
                    result.setMsg("规则为空，请先配置规则");
                    logger.error("规则为空，请先配置规则, param={}", param);
                    return result;
                }
                for (SalvationRuleEntity entity : list) {
                    SecurityParam securityParam = new SecurityParam();

                    securityParam.setStandardMoney(standardMoney);
                    Hashtable<String, Object> varValues = diBaoValueConvert(param);
                    securityParam.setName(entity.getName());
                    securityParam.setSalvationTarget(entity.getSalvationTarget());
                    if (param.getTypeName().indexOf("城市") != -1) {
                        varValues.put("城市标准", standardMoney);
                    } else {
                        varValues.put("农村标准", standardMoney);
                    }
                    String str = entity.getChineseFormula();
                    if (StringUtils.isNotBlank(param.getDisabilityLevel())) {
                        FormulaConvert cvt = new FormulaConvert();
                        ArrayList<String> arr = cvt.SplitWord("{" + str + "}");
                        RefObject rnt = new RefObject(0);
                        ArrayList<ISentence> sts = BlockServer.build(arr, 0, rnt);

                        Map<String, Object> rnts = BlockServer.runCode(sts, varValues);
                        if (null != rnts && rnts.size() > 0) {
                            for (String k : rnts.keySet()) {
                                securityParam.setMoneyName(k);
                                securityParam.setMoney(rnts.get(k).toString());
                                securityList.add(securityParam);
                            }
                        }
                    } else {

                        FormulaConvert cvt = new FormulaConvert();
                        ArrayList<String> arr = cvt.SplitWord("{" + str + "}");
                        RefObject rnt = new RefObject(0);
                        ArrayList<ISentence> sts = BlockServer.build(arr, 0, rnt);

                        Map<String, Object> rnts = BlockServer.runCode(sts, varValues);
                        for (String k : rnts.keySet()) {
                            if (k.equals("分类救助金")) {
                                SecurityParam securityParam1 = new SecurityParam();
                                securityParam1.setMoneyName(k);
                                securityParam1.setMoney(rnts.get(k).toString());
                                securityList.add(securityParam1);
                            } else if (k.equals("特殊救助金")) {
                                SecurityParam securityParam1 = new SecurityParam();
                                securityParam1.setMoneyName(k);
                                securityParam1.setMoney(rnts.get(k).toString());
                                securityList.add(securityParam1);
                            } else if (k.equals("基本救助金")) {
                                securityParam.setMoneyName(k);
                                securityParam.setMoney(rnts.get(k).toString());
                                securityParam.setSalvationTarget(entity.getSalvationTarget());
                                securityList.add(securityParam);
                            }
                        }
                    }
                }
            }
            else {

                SecurityParam securityParam = new SecurityParam();

                securityParam.setStandardMoney(standardMoney);
                securityParam.setName("单人保");
                securityParam.setMoneyName("基本救助金");
                securityParam.setSalvationTarget("02");
                securityParam.setMoney(String.valueOf(param.getSalaryNumber()));
                securityList.add(securityParam);
            }

            if (null == securityList || securityList.size() == 0) {
                result.setCode("400");
                result.setMsg(String.format("根据标准(%s)计算待遇金额为空，请检查政策配置是否正确", param.getFormulaValue()));
                result.setData(securityList);
                logger.error("根据标准计算待遇金额为空, param={}", param);
                return result;
            }
            moneyRound(securityList);
            result.setData(securityList);
        } catch (Exception e1) {
            logger.error("待遇计算出错, {}", param, e1);
            result.setCode(FailureCode.ERR_20017.getCode());
            result.setMsg(e1.getMessage());
        }
        return result;
    }


    @Override
    public BaseResult<List<SecurityParam>> diBaoFormulCount(FormulCountParam param) {
        BaseResult<List<SecurityParam>> result = new BaseResult<>();
        List<SecurityParam> securityList = new ArrayList<>();

        if (CommonUtil.invalidArgs(param.getAreaCode(), param.getBusinessType(), param.getTaOrgId(),
                param.getTypeName())) {
            result.setCode(FailureCode.ERR_10000.getCode());
            result.setMsg(FailureCode.ERR_10000.getMessage());
            return result;
        }
        param.setAreaCode(param.getAreaCode());
        param.setBusinessType(param.getBusinessType());
        param.setTaOrgId(param.getTaOrgId());
        param.setSaveType(Constant.SaveType.ZHB);
        try {
            if (param.getTypeName().indexOf("城市") != -1) {
                param.setType("01");
            } else {
                param.setType("02");
            }

            Double standardMoneys = standardReadService.getStandardMoney(param.getWelfareId(), param.getAreaCode().substring(0,6)+"000000", param.getBusinessType(), param.getType());
            Double standardMoney;
            if (null == standardMoneys) {
                result.setCode("300");
                result.setMsg("标准为零，请先配置标准");
                return result;
            }else{
                standardMoney = Double.parseDouble(standardMoneys.toString());
            }


            if (null != param.getIncome() && param.getIncome()  >= standardMoney) {
                result.setCode("300");
                result.setMsg("家庭收入大于救助标准");
                return result;
            }

            List<SalvationRuleEntity> list = salvationRuleReadService.queryRuleCount(param);
            if (null == list || list.size() == 0) {
                result.setCode("400");
                result.setMsg("规则为空，请先配置规则");
                logger.error("规则为空，请先配置规则, param={}", param);
                return result;
            }
            for (SalvationRuleEntity entity : list) {
                SecurityParam securityParam = new SecurityParam();

                securityParam.setStandardMoney(standardMoney);
                Hashtable<String, Object> varValues = diBaoValueConvert(param);

                if (null != varValues && !CommonUtil.invalidArgs(varValues.get("保障金计算方式"))) {
                    String name = varValues.get("保障金计算方式").toString();

                    String typeName = param.getTypeName().substring(0,2) + name;
                    if (name.indexOf("档") != -1) {
                        Map<String, Object> standParam = new HashMap<>();
                        standParam.put("status", Constant.StandardStatus.ENABLE);
                        standParam.put("typeName", typeName);
                        standParam.put("welfareId", param.getWelfareId());
                        standParam.put("orgId", param.getTaOrgId());
                        standParam.put("areaCode", param.getAreaCode().substring(0,6)+"000000");
                        StandardEntity saentity = standardReadService.querySalvationStandard(standParam);
                        if(null != saentity ) {
                            String saentityTypeName = saentity.getType();
                            securityParam.setTypeName(saentityTypeName);
                            securityParam.setTypeMoney(saentity.getStandardMoney());
                            saentityTypeName = saentityTypeName.substring(0,4) + "标准救助金额";
                            varValues.put(saentityTypeName, saentity.getStandardMoney());
                        }else {

                            if(!CommonUtil.invalidArgs(entity.getChineseFormula())&&entity.getChineseFormula().indexOf("档")==-1) {
                                varValues.put("家庭月总收入", 0);
                            }else {
                                result.setCode("300");
                                result.setMsg("标准为零，请先配置标准");
                                result.setData(securityList);
                                return result;
                            }
                        }
                    }
                    if (name.indexOf("补差") != -1) {
                        varValues.put("家庭月总收入", param.getIncome());
                        varValues.put("家庭人均月收入", param.getIncome());
                    }
                }
                securityParam.setName(entity.getName());
                securityParam.setSalvationTarget(entity.getSalvationTarget());
                if (param.getTypeName().indexOf("城市") != -1) {
                    varValues.put("城市标准", standardMoney);
                } else {
                    varValues.put("农村标准", standardMoney);
                }

                String str = entity.getChineseFormula();
                if (StringUtils.isNotBlank(param.getDisabilityLevel())) {
                    FormulaConvert cvt = new FormulaConvert();
                    ArrayList<String> arr = cvt.SplitWord("{" + str + "}");
                    RefObject rnt = new RefObject(0);
                    ArrayList<ISentence> sts = BlockServer.build(arr, 0, rnt);

                    Map<String, Object> rnts = BlockServer.runCode(sts, varValues);
                    if (null != rnts && rnts.size() > 0) {
                        for (String k : rnts.keySet()) {
                            securityParam.setMoneyName(k);
                            securityParam.setMoney(rnts.get(k).toString());
                            securityList.add(securityParam);
                        }
                    }
                } else {

                    FormulaConvert cvt = new FormulaConvert();
                    ArrayList<String> arr = cvt.SplitWord("{" + str + "}");
                    RefObject rnt = new RefObject(0);
                    ArrayList<ISentence> sts = BlockServer.build(arr, 0, rnt);

                    Map<String, Object> rnts = BlockServer.runCode(sts, varValues);
                    for (String k : rnts.keySet()) {
                        if (k.equals("分类救助金")) {
                            SecurityParam securityParam1 = new SecurityParam();
                            securityParam1.setMoneyName(k);
                            securityParam1.setMoney(rnts.get(k).toString());
                            securityList.add(securityParam1);
                        } else if (k.equals("特殊救助金")) {
                            SecurityParam securityParam1 = new SecurityParam();
                            securityParam1.setMoneyName(k);
                            securityParam1.setMoney(rnts.get(k).toString());
                            securityList.add(securityParam1);
                        } else if (k.equals("基本救助金")) {
                            securityParam.setMoneyName(k);
                            securityParam.setMoney(rnts.get(k).toString());
                            securityParam.setSalvationTarget(entity.getSalvationTarget());
                            securityList.add(securityParam);
                        }
                    }
                }
            }

            if (null == securityList || securityList.size() == 0) {
                result.setCode("400");
                result.setMsg(String.format("根据标准(%s)计算待遇金额为空，请检查政策配置是否正确", param.getFormulaValue()));
                result.setData(securityList);
                logger.error("根据标准计算待遇金额为空, param={}", param);
                return result;
            }
            moneyRound(securityList);
            result.setData(securityList);
        } catch (Exception e1) {
            logger.error("待遇计算出错, {}", param, e1);
            result.setCode(FailureCode.ERR_20017.getCode());
            result.setMsg(e1.getMessage());
        }
        return result;
    }

}
